#include "map.h"

Space::Space()
{
  d = '.';
  fore = COLOR_WHITE;
  back= COLOR_BLACK;
  isOpenDoor = false;
  isClosedDoor = false;
  inSpace = new MovableList();
  type = 0;
}

Space::Space(bool w, bool door)
{
  isWall = w;
  isClosedDoor = door;
  isOpenDoor = false;
  d = '.';
  fore = COLOR_WHITE;
  back = COLOR_BLACK;
  if (w)
  {
    d = '#';
    fore = COLOR_YELLOW;
  }
  if (door)
  {
    d = '+';
  }
  baseFore = fore;
  baseBack = back;
  baseD = d;
  type = 0;
  inSpace = new MovableList();
}

void Space::restoreBase()
{
  d = baseD;
  fore = baseFore;
  back = baseBack;
}

void Space::addPlayer(Player* p)
{
  inSpace->insertFront(p);
  d = p->getSymbol();
  fore = p->getFore();
  back = p->getBack();
}

void Space::addMonster(Monster* m)
{
  inSpace->insertBack(m);
  d = m->getSymbol();
  fore = m->getFore();
  back = m->getBack();
}

Player* Space::getPlayer()
{
  if (inSpace->empty())
    return NULL;
  else if (inSpace->head->data->isPlayer())
    return (Player*) inSpace->head->data;
  else
    return NULL;
}

Monster* Space::getMonster()
{
  if (inSpace->empty())
    return NULL;
  else if (inSpace->head->data->isMonster())
    return (Monster*) inSpace->head->data;
  else
    return NULL;
}

void Space::removePlayer()
{
  inSpace->popFront();
  restoreBase();
}

void Space::removeMonster(Monster* m)
{
  // TODO: Verify m is in this space.
  inSpace->popFront();
  restoreBase();
}

char Space::display()
{
  return d;
}

char Space::displayBase()
{
  return baseD;
}

int Space::getFore()
{
  return fore;
}

int Space::getBack()
{
  return back;
}

int Space::getType()
{
  return type;
}

bool Space::passable()
{
  if (isWall)
    return false;
  if (inSpace->empty())
    return true;
  if (inSpace->head->data->isCreature())
    return false;
}

bool Space::isClosed()
{
  return isClosedDoor;
}

bool Space::isOpen()
{
  return isOpenDoor;
}

void Space::closeDoor()
{
  isClosedDoor = true;
  isOpenDoor = false;
  d = '+';
  baseD = '+';
}

void Space::openDoor()
{
  isClosedDoor = false;
  isOpenDoor = true;
  d = '\'';
  baseD = '\'';
}

void Space::load(int i)
{
  switch (i)
  {
    case 0 :
      return;
    case 1 :
      baseFore = COLOR_BLUE;
      fore = COLOR_BLUE;
      type = 1;
      return;
  }
}

Map::Map()
{
  height = 20;
  width = 40;
  posX = 5;
  posY = 5;
  map = new Space**[height];
  for (int i = 0; i < height; i++)
    map[i] = new Space*[width];

  Player* p = new Player(this);
  for (int i = 0; i < height; i++)
    for (int j = 0; j < width; j++)
    {
      if (i == posX && j == posY)
      {
        map[i][j] = new Space(false, false);
        map[i][j]->addPlayer(p);
      }
      else if (i == 0 || i == height - 1 || j == 0 || j == width - 1)
        map[i][j] = new Space(true, false);
      else
        map[i][j] = new Space();
    }
}

Map::Map(int i)
{
  height = 20;
  width = 40;
  posX = 2;
  posY = 2;
  map = new Space**[height];
  for (int i = 0; i < height; i++)
    map[i] = new Space*[width];

  Player* p = new Player(this);
  for (int i = 0; i < height; i++)
    for (int j = 0; j < width; j++)
    {
      if (i == posX && j == posY)
      {
        map[i][j] = new Space(false,false);
        map[i][j]->addPlayer(p);
      }
      else if (i == 0 || i == height - 1 || j == 0 || j == width - 1)
        map[i][j] = new Space(true, false);
      else
        map[i][j] = new Space();
    }

  map[4][1] = new Space(true, false);
  map[4][2] = new Space(true, false);
  map[4][3] = new Space(true, false);
  map[4][4] = new Space(true, false);
  map[3][4] = new Space(true, false);
  map[2][4] = new Space(false, true);
  map[1][4] = new Space(true, false);
}

Space* Map::getSpace(int i, int j)
{
  return map[i][j];
}

void Map::start()
{
  int status = 0;
  int turn = 0;

  while (status != -1)
  {
    creatures.at(turn)->makeMove();
//    if (status != 0 || DEBUG == 1)
//    {
//      S->addMessage(K->getMessage().c_str());
//      S->mesPrint();
//    }
    status = creatures.at(turn)->getStatus();
    if (turn + 1 < creatures.size())
      turn = turn + 1;
    else
      turn = 0;
  }
}

int Map::movePos(int x, int y)
{
  Player* temp;
  Monster* curMonster;
  if (posX + x < height && posX + x >= 0 && posY + y < width && posY + y >= 0)
  {
    if (map[posX + x][posY + y]->isClosed())
    {
      map[posX + x][posY + y]->openDoor();
      return 3;
    }
    if (map[posX + x][posY + y]->passable())
    {
      temp = map[posX][posY]->getPlayer();
      map[posX][posY]->removePlayer();
      posX = posX + x;
      posY = posY + y;
      map[posX][posY]->addPlayer(temp);
      return 0;
    }
    if ((curMonster = map[posX + x][posY + y]->getMonster()) != NULL)
    {
      return 4;
    }
    else
      return 1;
  }
  else
    return 2;
}

int Map::moveCreature(int ID, int x, int y)
{
  //if (ID == 0)
  // TODO:  Exit if ID is 0.  Also, sanity check this function.
  Monster* m = (Monster*) creatures[ID];
  map[m->getX()][m->getY()]->removeMonster(m);
  map[x][y]->addMonster(m);
}

int Map::getPosX()
{
  return posX;
}

int Map::getPosY()
{
  return posY;
}

int Map::getWidth()
{
  return width;
}

int Map::getHeight()
{
  return height;
}
